package com.myk.game.gobangchess.rooms.prerooms;

import com.myk.game.gobangchess.CustomBottom;
import com.myk.game.gobangchess.Player;
import com.myk.game.gobangchess.RobotPlayer;
import com.myk.game.gobangchess.constants.ColorCost;
import com.myk.game.gobangchess.constants.Msger;
import com.myk.game.gobangchess.expand.bwantispace.*;
import com.myk.game.gobangchess.rooms.absrooms.AbsAiRoom;
import com.myk.game.gobangchess.signs.*;
import com.myk.game.gobangchess.utils.GridsUtils;

import java.util.ArrayList;
import java.util.List;

/**
 * 《黑白逆界》单人pve生存游戏
 */
public class BWAntiSpaceRoom extends AbsAiRoom {

    //++for循环+sleep改成递归加Timer
    //++ Game类中的逻辑全都放到Helper中，game仅仅只是个实体类

    //房间工具代码的封装类
    public final Manager manager;
    //一整个游戏环境，点击开始游戏会生成新，每个用户能在后台保留一个存档
    private Game game;

    public BWAntiSpaceRoom(String roomName) {
        super(roomName, "单人生存游戏，收集道具，击杀怪物，在不断生成的怪物潮中尽可能的生存下去！", "黑白逆界", GridsUtils.createEmptyGrids(15, 15), true, false);
        manager = new Manager(this);
    }

    @Override
    public String getRuleText() {
        return "暂未编写";
    }

    @Override
    protected void onStartPrepare() {
        Player humanPlayer = manager.getHumanPlayer();
        if (humanPlayer != null){
            CustomBottom saveFile = new CustomBottom(this, "保存存档", (player1) -> {
                if (getCurPlayer() == humanPlayer){
                    humanPlayer.sendMessage(Msger.broadcast,"保存存档后期再实现");
                }
            });
            CustomBottom startGame = new CustomBottom(this, "开始游戏", (player) -> {
                humanPlayer.clearCustomBottom();
                //humanPlayer.registerCustomBottom(saveFile);
                humanPlayer.dispatchCustomBottom();
                game = new Game(this);
                game.start();
            });
            CustomBottom loadFile = new CustomBottom(this, "加载存档", (player) -> {
                humanPlayer.sendMessage(Msger.broadcast,"加载存档功能后期再实现");
            });
            humanPlayer.registerCustomBottom(startGame);
            //humanPlayer.registerCustomBottom(loadFile);
        }
    }

    @Override
    public void doOver(int winMode, String winMsg) {
        game = null; //游戏结束了记得清除game
        super.doOver(winMode, winMsg);
    }

    @Override
    public void doRule(int row, int col, int value) {
        if (game != null){
            game.doRule(row, col); //让当前游戏逻辑去处理玩家的点击操作
        }
    }

    @Override
    public String getGameInfo() {
        curGrids = GridsUtils.copyGrids(originGrids);
        signList.clear();
        //没有开始游戏的时候显示海报页面
        if (game == null){
            signList.add(new GroundSign(getIndex(0,0),getIndex(curGrids.length-1,curGrids[0].length-1), ColorCost.BLACK, ColorCost.BLUE_BOARD_LINE, 5f));
            signList.add(new TitleSign(0.5f,0.45f,0,"黑白逆界",ColorCost.WHITE,2f));
        }
        //游戏进行中让游戏自己去绘制
        else {
            game.render();
        }
        return super.getGameInfo();
    }

    @Override
    public String getCoordMode() {
        return "00000000"; //不显示坐标
    }

    @Override
    protected Player createRobotPlayer() {
        return new RobotPlayer(this, "jk123456bwnj", "#逆界", () -> {
            sleep(100);
            game.update();
        });
    }

    /**
     * 房间环境需要的辅助代码的封装
     */
    public static class Manager {
        private final BWAntiSpaceRoom room;

        public Manager(BWAntiSpaceRoom room) {
            this.room = room;
        }

        /**
         * 设置游戏提示文本
         */
        public void setGameTip(String tipMsg){
            room.setGameTip(tipMsg);
        }

        /**
         * 获取真人玩家对象
         */
        public Player getHumanPlayer(){
            if (room.player_black instanceof RobotPlayer){
                return room.player_white;
            }
            if (room.player_white instanceof RobotPlayer){
                return room.player_black;
            }
            return null;
        }

        /**
         * 通知真人玩家行动
         */
        public void noticeHumanMove() {
            if (room.player_black instanceof RobotPlayer){
                room.noticeWhiteMove();
            }
            if (room.player_white instanceof RobotPlayer){
                room.noticeBlackMove();
            }
        }

        /**
         * 通知ai行动
         */
        public void noticeRobotMove() {
            if (room.player_black instanceof RobotPlayer){
                room.noticeBlackMove();
            }
            if (room.player_white instanceof RobotPlayer){
                room.noticeWhiteMove();
            }
        }

        /**
         * 显示信息对话框
         */
        public void showInfoDialog(String info) {
            Player player = getHumanPlayer();
            if (player != null){
                player.sendMessage(Msger.showInfoDialog, info);
            }
        }

        /**
         * 获取场上一个随机的空格
         */
        public int[] getRandomEmptyPosition(){
            List<int[]> emptyPositionList = new ArrayList<>();
            for (int i = 0; i < room.curGrids.length; i++) {
                for (int j = 0; j < room.curGrids[0].length; j++) {
                    if (room.curGrids[i][j] == 0){
                        emptyPositionList.add(new int[]{i,j});
                    }
                }
            }
            if (emptyPositionList.size() == 0){
                return null;
            }
            else {
                return emptyPositionList.get((int)(Math.random() * emptyPositionList.size()));
            }
        }

        /**
         * 获取棋盘边缘一个随机的空格
         */
        public int[] getRandomBoardSideEmptyPosition(){
            List<int[]> emptyPositionList = new ArrayList<>();
            for (int i = 0; i < room.curGrids.length; i++) {
                for (int j = 0; j < room.curGrids[0].length; j++) {
                    if (room.curGrids[i][j] == 0){
                        if (i == 0 || i == room.curGrids.length-1 || j == 0 || j == room.curGrids[0].length-1){
                            emptyPositionList.add(new int[]{i,j});
                        }
                    }
                }
            }
            if (emptyPositionList.size() == 0){
                return null;
            }
            else {
                return emptyPositionList.get((int)(Math.random() * emptyPositionList.size()));
            }
        }

        /**
         * 判断该点是否在棋盘内
         */
        public boolean isInGrids(int row, int col) {
            return row >= 0 && row < room.curGrids.length && col >= 0 && col < room.curGrids[0].length;
        }

        /**
         * 获取两个坐标之间的距离长度
         */
        public int getDistance(int row1, int col1, int row2, int col2){
            return Math.abs(row1 - row2) + Math.abs(col1 - col2);
        }

        /**
         * 获取指定坐标，指定格子数可到达的范围集合，不能越过阻挡
         */
        public List<int[]> getCanMovedPos(int row, int col, int sp) {
            List<int[]> canMovedPosList = new ArrayList<>();
            int[] originPoint = new int[]{row, col};
            canMovedPosList.add(originPoint); //原位置也能落下
            int dis = 1;
            while (dis <= sp) { //由原位置向外扩展搜索三次
                moveSearch(originPoint, canMovedPosList, dis);
                dis++;
            }
            canMovedPosList.remove(originPoint); //最后再去除原位置
            return duplicateList(canMovedPosList); //去重后返回
        }

        //移动路径搜索
        private void moveSearch(int[] target, List<int[]> canMovedPosList, int dis) {
            List<int[]> addList = new ArrayList<>();
            for (int[] ints : canMovedPosList) {
                if (getDistance(target, ints) == dis - 1) { //只有最外面一圈的有资格扩展
                    List<int[]> aroundList = getAroundList(ints); //获取每个格子周围一圈的格子
                    for (int[] ints1 : aroundList) {
                        if (isInGrids(ints1[0],ints1[1]) && getDistance(target, ints1) == dis && room.curGrids[ints1[0]][ints1[1]] == 0) { //再把不符合要求的格子排除掉
                            addList.add(ints1);
                        }
                    }
                }
            }
            canMovedPosList.addAll(addList);
        }

        //去除List列表中重复值方法一：普通的方法,利用for循环去重
        private List<int[]> duplicateList(List<int[]> list) {
            for (int i = 0; i < list.size() - 1; i++) {
                for (int j = list.size() - 1; j > i; j--) {
                    int[] item = list.get(i);
                    int[] jtem = list.get(j);
                    if (item[0] == jtem[0] && item[1] == jtem[1]) {
                        list.remove(j);
                    }
                }
            }
            return list;
        }

        //获取某个格子坐标四周的格子坐标列表 （不管是否超出棋盘外）
        private List<int[]> getAroundList(int[] ints) {
            List<int[]> aroundList = new ArrayList<>();
            aroundList.add(new int[]{ints[0] - 1, ints[1]});
            aroundList.add(new int[]{ints[0] + 1, ints[1]});
            aroundList.add(new int[]{ints[0], ints[1] - 1});
            aroundList.add(new int[]{ints[0], ints[1] + 1});
            return aroundList;
        }

        //获取两个坐标之间的距离长度
        private int getDistance(int[] target, int[] ints) {
            return Math.abs(target[0] - ints[0]) + Math.abs(target[1] - ints[1]);
        }

    }

}
